var abils         = ['str',  'dex',    'con', 'int', 'wis', 'cha'];
var abil_lbls     = ['Str',  'Dex',    'Con', 'Int', 'Wis', 'Cha'];
var abilmods      = ['base', 'race',   'enh', 'misc'];
var abilmod_lbls  = ['Base', 'Racial', 'Enh', 'Misc'];
var atkFields =     [['weap',    'Weapon',        16],
                     ['atk',     'Atk',            3],
                     ['dmg',     'Damage',         7],
                     ['enh',     'M.Enh',          3],
                     ['crit',    'Crit',           9],
                     ['range',   'Range Incr.',    4],
                     ['dmgtype', 'Type',           3],
                     ['ammo',    'Comments/Ammo', 20]];
var atkPubs = ['atk', 'enh', 'dmg', 'range'];
var maxAttack = 0;

function subscribe(publisher, recalc)
{
    if(!subscribe.FirstAlert) subscribe.firstAlert = true;
    if(publisher.notify)
    {
        var tempfunc = publisher.notify;
        publisher.notify = function(){ tempfunc(); recalc(); }
        publisher.onchange = publisher.notify;
        subscribers.push(recalc);
    }
    else if(subscribe.firstAlert) 
    {
        alert('attempted to add subscriber to non-publisher (' + publisher.id + ')'); 
        subscribe.firstAlert = false;
    }
}

function createAbility(id, name)
{
    var moddiv = document.createElement('div')
        moddiv.setAttribute('class', 'inbl pad box');
        moddiv.appendChild(createConnector('+'));
        f = createLabeledField('mod' + id, 'Mod', '', 4, false, NOPAD);
        moddiv.appendChild(f);
        
    var ret = document.createElement('div');
        ret.appendChild(createLabeledField('abil' + id,  name, '', 4, false, NOPAD));
        ret.appendChild(createConnector('='));
        
        for (i in abilmods)
        {
          appendCaptionedField(ret, id + '_' + abilmods[i], abilmod_lbls[i], '', 4, true, NOPAD);
          ret.appendChild(createConnector('+', NOPAD));
        }
        ret.removeChild(ret.lastChild); /*remove trailing "+"*/
   
        ret.appendChild(moddiv);
        ret.appendChild(createListEnder());
    
    return ret;
}

function appendAbility(p, id, name)
{
    var f = createAbility(id, name);
    p.appendChild(f);
}

function createAbilityBlock()
{
    var ret = document.createElement('div');
        ret.setAttribute('class', 'inbl pad box');        
        for (i in abils) {
          appendAbility(ret, abils[i], abil_lbls[i]); }

    return ret;
}

function appendAbilityBlock(p)
{ p.appendChild(createAbilityBlock()); }

function createAttack()
{
    maxAttack += 1;
    
    var del = createActionBlank('delAttackBlock', 'del');
        del.onclick = function(){ deleteFromContaining(ret); };
            
    var ret = document.createElement('div');
        ret.setAttribute('class', 'pad box');
        for (i in atkFields)
        {
            appendLabeledField(ret, atkFields[i][0] + maxAttack,
                               atkFields[i][1], '', atkFields[i][2], true, NOPAD);
            switch(atkFields[i][0]) {
                case 'atk':  ret.appendChild(createConnector('(', NOPAD)); break;
                case 'enh':  ret.appendChild(createConnector(')', NOPAD)); break;
                case 'crit': ret.appendChild(createListEnder());    break; }
        }
        ret.appendChild(del);
        ret.appendChild(createListEnder());
        
    return ret;
}

function createAttacksBlock()
{
    var f = createLabeledField('bab', 'BAB', '', 3, true, PADDED);
                
    var add = createActionBlank('addAttackBlock', 'add');
        add.onclick = function(){ ret.insertBefore(createAttack(), add); 
                                  setupAttackCalcs(maxAttack); };
        
    var ret = document.createElement('div');
        ret.setAttribute('class', 'inbl pad box');
        ret.appendChild(f);
        ret.appendChild(createListEnder());
        ret.appendChild(add);
    
    return ret;
}

function appendAttacksBlock(p)
{ p.appendChild(createAttacksBlock()); }

function setupAbilCalcs()
{
    for (i in abils) 
    {
        var handles = [];
        var score = document.getElementById('abil' + abils[i]);
        var mod   = document.getElementById('mod'  + abils[i]);
        
        mod.recalc = function (m, s) { return function() {
                         m.value = Math.floor( (s.value - 10) / 2 );
                         m.notify(); };
        }(mod, score);
        
        subscribe(score, mod.recalc);

        for (j in abilmods) {
            handles[j] = document.getElementById(abils[i] + '_' + abilmods[j]); }
        
        score.recalc = function (s, h) { return function() {
                           var sum = 0;
                           for (j in h) 
                           {
                               var k = parseInt(h[j].value);
                               if (k) {
                                   sum += k;} 
                           }
                           s.value = sum;
                           s.notify(); }; 
                       }(score, handles);
        
        for (j in handles) {
            subscribe(handles[j], score.recalc); }
    }
}

function setupAttackCalcs(idx)
{
    var bab = document.getElementById('bab');
    var str = document.getElementById('modstr');
    var dex = document.getElementById('moddex');
    
    var atklbl = 'atk'   + idx;
    var enhlbl = 'enh'   + idx;
    var dmglbl = 'dmg'   + idx;
    var rnglbl = 'range' + idx;
    
    var atk = document.getElementById(atklbl);
    if(atk)
    {
        var dmg   = document.getElementById(dmglbl);
        var range = document.getElementById(rnglbl);
        var enh   = document.getElementById(enhlbl);
    
        atk.recalc = function(a, r) { return function() {
                         if(r.value == 'M')             /* melee */
                             a.value = '+' + (zInt(bab.value) + zInt(str.value) + zInt(enh.value));
                         else if(parseInt(r.value) > 0) /* ranged */
                             a.value = '+' + (zInt(bab.value) + zInt(dex.value) + zInt(enh.value));
                         a.notify(); };
                     }(atk, range);
        
        atkSrcs = [bab, range, str, dex, enh];
        for (i in atkSrcs) {
            subscribe(atkSrcs[i], atk.recalc); }
        
        dmg.recalc = function (d, r) { return function(){
                         d.notify(); };
                     }(dmg, range);

        dmgSrcs = [range, str, dex];
        for (i in dmgSrcs) {
            subscribe(dmgSrcs[i], dmg.recalc); }
    }
}

function constructCombatTab()
{
    var p  = document.getElementById('tab-combat');
        if(p.lastChild && p.lastChild.className == 'endls')
        { p.removeChild(p.lastChild); }
        
        appendAbilityBlock(p);
        appendAttacksBlock(p);
        
        p.appendChild(createListEnder());

    setupAbilCalcs();
}

/* function below to be generated by python */
%(populateCombatTab)s
